package com.itheima.d2_buffered_stream;
import java.io.*;
import java.util.Arrays;

/**
 * 目标：掌握字节缓冲流的作用。
 *
 *  IO流的体系
 *    字节流：          抽象类          实现类(原始流/低级流)     实现类(包装流/处理流)
 *      字节输入流    InputStream      FileInputStream       字节缓冲输入流:BufferedInputStream
 *      字节输出流    OutputStream     FileOutputSteam       字节缓冲输出流:BufferedOutputStream
 *    字符流：
 *      字符输入流    Reader           FileReader            字符缓冲输入流:BufferedReader
 *      字符输出流    Writer           FileWriter            字符缓冲输出流:BufferedWriter
 *
 *  对原始流进行包装，以提高原始流读写数据的性能
 *
 *  字节缓冲流的作用：提高字节流读写数据的性能
 *  原理：
 *      字节缓冲输入流自带了8KB缓冲池；字节缓冲输出流也自带了8KB缓冲池。然后假设数据源16kb，内存中有一个1kb的字节数组,
 *      然后字节输入缓冲流可以一次加载8kb的数据到内存中的缓冲池来，共调用两次系统资源就可以通过字节输入缓冲流把数据源的数据取走
 *      字节输出缓冲流的8kb缓冲池满了后，就会输出到目的地的文件中
 *      字节输出缓冲流的8kb缓冲池，也只需要调用两次系统资源，就可以通过字节输出缓冲流把数据写入到文件中。共计4次。
 *      整个过程都是在内存中进行，速度很快，减少外存和内存的交互，减少了系统资源的调度，功能上并无很大变化，性能提升了
 *
 *  对比原始的字节输入输出流的复制案例：
 *      假设数据源16kb，内存中准备了一个1kb的字节数组，那么每次都是从字节输入流中读取1kb数据到字节数组，然后再写入到字节输出流中
 *      那么就意味着需要调用16次系统资源通过字节输入流读取数据，然后又要调用16次系统资源通过字节输出流把数据写到文件中。总计32次系统调用
 *
 *          构造器
 *  public BufferedInputStream(InputStream is)     把低级的字节输入流包装成一个高级的缓冲字节输入流，从而提高读数据的性能
 *  public BufferedOutputStream(OutputStream os)   把低级的字节输出流包装成一个高级的缓冲字节输出流，从而提高写数据的性能
 *
 *
 */
public class BufferedInputStreamTest1 {
    public static void main(String[] args) {
        try (
                InputStream is = new FileInputStream("Day09Io-App2/src/itheima01.txt");
                // 1、定义一个字节缓冲输入流包装原始的字节输入流
                // 可以看BufferedInputStream源码，里面创建了一个8192大小的字节数组:buf = new byte[size];
                InputStream bis = new BufferedInputStream(is);
                //8192*2把高级缓冲流里面的缓冲池字节数组8kb*2，变成16字节的
                //InputStream bis = new BufferedInputStream(is,8192*2);

                OutputStream os = new FileOutputStream("Day09Io-App2/src/itheima01_bak.txt");
                // 2、定义一个字节缓冲输出流包装原始的字节输出流
                OutputStream bos = new BufferedOutputStream(os);
                //OutputStream bos = new BufferedOutputStream(os,8192*2);

                //自己试一试：
                InputStream zInput = new FileInputStream("Day09Io-App2/src/itheima01.txt");
                InputStream zBuffR = new BufferedInputStream(zInput);
                OutputStream zOut = new FileOutputStream("Day09Io-App2/src/zengjihognShiyan.txt");
                OutputStream zBuffO = new BufferedOutputStream(zOut);

        ){

            byte[] buffer = new byte[1024];
            int len;
            while ((len = bis.read(buffer)) != -1){
                bos.write(buffer, 0, len);
            }
            System.out.println("复制完成！！");

            System.out.println("-------------------自己试一试----------");
            System.out.println(zInput.read());      //110
            System.out.println((char) zInput.read());   //a
            byte[] zengInput = new byte[3];
            int zLength = zInput.read(zengInput);
            System.out.println("每次读取返回的字节长度"+zLength);    //3
            System.out.println("字节数组： "+zengInput);   //[B@119d7047
            System.out.println("字节数组内容，未解码： "+Arrays.toString(zengInput));  //[115, 102, 106]
            System.out.println("解码后： "+ new String(zengInput));      //sfj
            System.out.println("------------------以上都是基础的字节输入流内容，下面就是字节输出流------------");

            zOut.write('z');
            byte zengOut[] = "季洪".getBytes();
            zOut.write(zengOut);
            zOut.write(zengInput);

            //zOut.write("\r\n");   //报错，因为这个是字节输出流，不能输入字符

            //改正：换行符，\n可能只能在Windows系统上面换行，而\r\n在各种系统上面都是支持换行
            zOut.write("\r\n".getBytes());        //把字符串编码成为字节
            System.out.println("-----------实验一下字节缓冲输入输出流------------------");

            byte[] zengBuff = new byte[3];
            int zengL;
            while ((zengL=zBuffR.read(zengBuff))!=-1){
                zBuffO.write(zengBuff,0,zengL);
            }
            System.out.println("复制到zengjihognShiyan.txt完成");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
